home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Visual Basic Source Code
/
Visual Basic Source Code.iso
/
vbsource
/
colorlab
/
modhslsm.bas
< prev
next >
Wrap
BASIC Source File
|
1999-09-28
|
9KB
|
283 lines
Attribute VB_Name = "modHSL"
Option Explicit
'For the FULL version of this module, please visit
' http://www.planet-source-code.com/vb
'(The darken & brighten routines in this module are
'slightly modified from that version)
'Portions of this code marked with *** are converted from
'C/C++ routines for RGB/HSL conversion found in the
'Microsoft Knowledge Base (PD sample code):
'http://support.microsoft.com/support/kb/articles/Q29/2/40.asp
'In addition to the language conversion, some internal
'calculations have been modified and converted to FP math to
'reduce rounding errors.
'Conversion to VB and original code by
'Dan Redding (bwsoft@revealed.net)
'http://home.revealed.net/bwsoft
'Free to use, please give proper credit
Public Const HSLMAX As Integer = 240 '***
'H, S and L values can be 0 - HSLMAX
'240 matches what is used by MS Win;
'any number less than 1 byte is OK;
'works best if it is evenly divisible by 6
Const RGBMAX As Integer = 255 '***
'R, G, and B value can be 0 - RGBMAX
Const UNDEFINED As Integer = (HSLMAX * 2 / 3) '***
'Hue is undefined if Saturation = 0 (greyscale)
Public Type HSLCol 'Datatype used to pass HSL Color values
Hue As Integer
Sat As Integer
Lum As Integer
End Type
Public Function RGBRed(RGBCol As Long) As Integer
'Return the Red component from an RGB Color
RGBRed = RGBCol And &HFF
End Function
Public Function RGBGreen(RGBCol As Long) As Integer
'Return the Green component from an RGB Color
RGBGreen = ((RGBCol And &H100FF00) / &H100)
End Function
Public Function RGBBlue(RGBCol As Long) As Integer
'Return the Blue component from an RGB Color
RGBBlue = (RGBCol And &HFF0000) / &H10000
End Function
Private Function iMax(a As Integer, B As Integer) _
As Integer
'Return the Larger of two values
iMax = IIf(a > B, a, B)
End Function
Private Function iMin(a As Integer, B As Integer) _
As Integer
'Return the smaller of two values
iMin = IIf(a < B, a, B)
End Function
Public Function RGBtoHSL(RGBCol As Long) As HSLCol '***
'Returns an HSLCol datatype containing Hue, Luminescence
'and Saturation; given an RGB Color value
Dim R As Integer, G As Integer, B As Integer
Dim cMax As Integer, cMin As Integer
Dim RDelta As Double, GDelta As Double, _
BDelta As Double
Dim H As Double, s As Double, L As Double
Dim cMinus As Long, cPlus As Long
R = RGBRed(RGBCol)
G = RGBGreen(RGBCol)
B = RGBBlue(RGBCol)
cMax = iMax(iMax(R, G), B) 'Highest and lowest
cMin = iMin(iMin(R, G), B) 'color values
cMinus = cMax - cMin 'Used to simplify the
cPlus = cMax + cMin 'calculations somewhat.
'Calculate luminescence (lightness)
L = ((cPlus * HSLMAX) + RGBMAX) / (2 * RGBMAX)
If cMax = cMin Then 'achromatic (r=g=b, greyscale)
s = 0 'Saturation 0 for greyscale
H = UNDEFINED 'Hue undefined for greyscale
Else
'Calculate color saturation
If L <= (HSLMAX / 2) Then
s = ((cMinus * HSLMAX) + 0.5) / cPlus
Else
s = ((cMinus * HSLMAX) + 0.5) / (2 * RGBMAX - cPlus)
End If
'Calculate hue
RDelta = (((cMax - R) * (HSLMAX / 6)) + 0.5) / cMinus
GDelta = (((cMax - G) * (HSLMAX / 6)) + 0.5) / cMinus
BDelta = (((cMax - B) * (HSLMAX / 6)) + 0.5) / cMinus
Select Case cMax
Case CLng(R)
H = BDelta - GDelta
Case CLng(G)
H = (HSLMAX / 3) + RDelta - BDelta
Case CLng(B)
H = ((2 * HSLMAX) / 3) + GDelta - RDelta
End Select
If H < 0 Then H = H + HSLMAX
End If
RGBtoHSL.Hue = CInt(H)
RGBtoHSL.Lum = CInt(L)
RGBtoHSL.Sat = CInt(s)
End Function
Public Function HSLtoRGB(HueLumSat As HSLCol) As Long '***
Dim R As Double, G As Double, B As Double
Dim H As Double, L As Double, s As Double
Dim Magic1 As Double, Magic2 As Double
H = HueLumSat.Hue
L = HueLumSat.Lum
s = HueLumSat.Sat
If CInt(s) = 0 Then 'Greyscale
R = (L * RGBMAX) / HSLMAX 'luminescence,
'converted to the proper range
G = R 'All RGB values same in greyscale
B = R
If CInt(H) <> UNDEFINED Then
'This is technically an error.
'The RGBtoHSL routine will always return
'Hue = UNDEFINED (160 when HSLMAX is 240)
'when Sat = 0.
'if you are writing a color mixer and
'letting the user input color values,
'you may want to set Hue = UNDEFINED
'in this case.
End If
Else
'Get the "Magic Numbers"
If L <= HSLMAX / 2 Then
Magic2 = (L * (HSLMAX + s) + 0.5) / HSLMAX
Else
Magic2 = L + s - ((L * s) + 0.5) / HSLMAX
End If
Magic1 = 2 * L - Magic2
'get R, G, B; change units from HSLMAX range
'to RGBMAX range
R = (HuetoRGB(Magic1, Magic2, H + (HSLMAX / 3)) _
* RGBMAX + 0.5) / HSLMAX
G = (HuetoRGB(Magic1, Magic2, H) * RGBMAX + 0.5) / HSLMAX
B = (HuetoRGB(Magic1, Magic2, H - (HSLMAX / 3)) _
* RGBMAX + 0.5) / HSLMAX
End If
HSLtoRGB = RGB(CInt(R), CInt(G), CInt(B))
End Function
Private Function HuetoRGB(mag1 As Double, mag2 As Double, _
ByVal Hue As Double) As Double '***
'Utility function for HSLtoRGB
'Range check
If Hue < 0 Then
Hue = Hue + HSLMAX
ElseIf Hue > HSLMAX Then
Hue = Hue - HSLMAX
End If
'Return r, g, or b value from parameters
Select Case Hue 'Values get progressively larger.
'Only the first true condition will execute
Case Is < (HSLMAX / 6)
HuetoRGB = (mag1 + (((mag2 - mag1) * Hue + _
(HSLMAX / 12)) / (HSLMAX / 6)))
Case Is < (HSLMAX / 2)
HuetoRGB = mag2
Case Is < (HSLMAX * 2 / 3)
HuetoRGB = (mag1 + (((mag2 - mag1) * _
((HSLMAX * 2 / 3) - Hue) + _
(HSLMAX / 12)) / (HSLMAX / 6)))
Case Else
HuetoRGB = mag1
End Select
End Function
Public Function ContrastingColor(RGBCol As Long) As Long
'Returns Black or White, whichever will show up better
'on the specified color.
'Useful for setting label forecolors with transparent
'backgrounds (send it the form backcolor - RGB value, not
'system value!)
'(also produces a monochrome negative when applied to
'all pixels in an image)
Dim HSL As HSLCol
HSL = RGBtoHSL(RGBCol)
If HSL.Lum > HSLMAX / 2 Then ContrastingColor = 0 _
Else: ContrastingColor = &HFFFFFF
End Function
Public Function Brighten(RGBColor As Long, Percent As Single)
'Lightens the color by a specifie percent, given as a Single
'(10% = .10)
Dim HSL As HSLCol, L As Long
If Percent <= 0 Then
Brighten = RGBColor
Exit Function
End If
HSL = RGBtoHSL(RGBColor)
L = HSL.Lum + (HSLMAX * Percent)
If L > HSLMAX Then L = HSLMAX
HSL.Lum = L
Brighten = HSLtoRGB(HSL)
End Function
Public Function Darken(RGBColor As Long, Percent As Single)
'Darkens the color by a specifie percent, given as a Single
Dim HSL As HSLCol, L As Long
If Percent <= 0 Then
Darken = RGBColor
Exit Function
End If
HSL = RGBtoHSL(RGBColor)
L = HSL.Lum - (HSLMAX * Percent)
If L < 0 Then L = 0
HSL.Lum = L
Darken = HSLtoRGB(HSL)
End Function
Public Function Blend(RGB1 As Long, RGB2 As Long, _
Percent As Single) As Long
'This one doesn't really use the HSL routines, just the
'RGB Component routines. I threw it in as a bonus ;)
'Takes two colors and blends them according to a
'percentage given as a Single
'For example, .3 will return a color 30% of the way
'between the first color and the second.
'.5, or 50%, will be an even blend (halfway)
'Can create some nice effects inside a For loo